Skip to content

Add embedded surface policies for Cherrypick file editor#2

Merged
soyboyscout merged 8 commits into
mainfrom
feat/code-editor
Jun 21, 2026
Merged

Add embedded surface policies for Cherrypick file editor#2
soyboyscout merged 8 commits into
mainfrom
feat/code-editor

Conversation

@soyboyscout

@soyboyscout soyboyscout commented Jun 20, 2026

Copy link
Copy Markdown
Member

Objective

Cherrypick embeds Zed's project panel, pane, and editor as a restricted file browser/editor surface. The embedded surface needs curated context menus because Cherrypick owns workspace-level actions such as terminal launch, git workflows, agent actions, and folder management.

This is not intended to add a standalone Zed product setting. Normal Zed behavior remains the default through the full() policy presets.

Solution

  • Add small public policy types for embedded hosts:
    • EditorSurfacePolicy
    • ProjectPanelContextMenuPolicy
    • PaneContextMenuPolicy
  • Provide full() presets for standard Zed behavior and embedded() presets for Cherrypick's restricted file browser/editor surface.
  • Add setter APIs so Cherrypick can apply the embedded policies from its host surface without wiring those policies into standalone Zed app flows.
  • Make ProjectPanel::reveal_abs_path use the panel's canonical self.project internally, avoiding mixed-project state from external callers.
  • Seed missing expanded-root state during absolute-path reveal so early reveal/select calls do not no-op before the project panel has initialized all expansion state.
  • Preserve editor surface policy across Editor::clone.

Testing

Zed fork checks:

  • CARGO_TARGET_DIR=/tmp/cherrypick-zed-feat-code-editor-target cargo +1.95.0 test -p editor test_clone
  • CARGO_TARGET_DIR=/tmp/cherrypick-zed-feat-code-editor-target cargo +1.95.0 test -p editor test_embedded_surface_policy_hides_host_owned_actions
  • CARGO_TARGET_DIR=/tmp/cherrypick-zed-feat-code-editor-target cargo +1.95.0 test -p project_panel test_embedded_project_panel_context_menu_policy_hides_host_owned_actions
  • CARGO_TARGET_DIR=/tmp/cherrypick-zed-feat-code-editor-target cargo +1.95.0 test -p project_panel test_reveal_abs_path_seeds_missing_expanded_state
  • CARGO_TARGET_DIR=/tmp/cherrypick-zed-feat-code-editor-target cargo +1.95.0 test -p workspace test_embedded_pane_context_menu_policy_hides_host_owned_actions
  • git diff --check

Cherrypick consumer checks:

  • CARGO_TARGET_DIR=/tmp/cherrypick-feat-code-editor-pr2-target cargo +1.95.0 test -p cherrypick-ui zed_files_host --lib
  • CARGO_TARGET_DIR=/tmp/cherrypick-feat-code-editor-pr2-target cargo +1.95.0 build --release -p cherrypick-ui --bin cherrypick
  • Relaunched /tmp/cherrypick-feat-code-editor-pr2-target/release/cherrypick; startup log reports MCP bridge listening.

Self-Review Checklist

  • I've reviewed my own diff for quality, security, and reliability
  • Unsafe blocks are not introduced by this change
  • The content adheres to Zed's UI standards; this only gates existing menu actions for an embedded host
  • Tests cover the new/changed behavior
  • Performance impact has been considered and is acceptable

Reviewer Context

The policy setters are consumed from Cherrypick's zed_files_host.rs, outside this Zed fork repository. Review comments that report the setters as unused in standalone Zed are expected from a Zed-only diff; the Cherrypick consumer build above verifies the integration point.

Release Notes:

  • Added embedded-surface context menu policies used by Cherrypick's Zed-backed file browser/editor.

Summary by CodeRabbit

  • New Features
    • Added configurable action-group visibility policies for editors, project panels, and panes (e.g., embedded vs full behavior).
    • Introduced selection controls UI for editors, including a dedicated toolbar item and menu.
    • Added project panel API to reveal/select entries by absolute filesystem path.
    • Exposed a workspace modal-layer accessor for external embedders.
    • Added a public helper to toggle the file finder modal.
  • Bug Fixes
    • Selection-menu change events now fire only when the enabled state actually changes.
  • Tests
    • Added coverage for embedded policy behavior, reveal-by-path state seeding, and toolbar toggle behavior.

Copilot AI review requested due to automatic review settings June 20, 2026 22:38
@matterai-app

matterai-app Bot commented Jun 20, 2026

Copy link
Copy Markdown

Summary By MatterAI MatterAI logo

🔄 What Changed

Implemented a reactive event system for the editor's selection menu. Added SelectionMenuChanged to EditorEvent and updated EditorSelectionControls to subscribe to this event, ensuring the toolbar location updates dynamically when the menu state toggles. This builds upon previous work standardizing context-menu policies to embedded surfaces.

🔍 Impact of the Change

Ensures UI consistency between the editor's internal state and the toolbar. When the selection menu is toggled (e.g., in the Cherrypick file editor), the toolbar items now correctly hide or reposition themselves immediately, improving the reliability of embedded surface policies.

📁 Total Files Changed

Click to Expand
File ChangeLog
Event Logic crates/editor/src/editor.rs Added SelectionMenuChanged event and emission logic in toggle_selection_menu.
UI Subscription crates/editor/src/selection_controls.rs Added subscription to editor events to trigger toolbar location updates and added unit tests.

🧪 Test Added/Recommended

Added

  • selection_menu_toggle_updates_toolbar_location: Verifies that toggling the selection menu in the editor correctly triggers a ChangeLocation event in the toolbar controls.

Recommended

  • Add a regression test to ensure that cloning an editor preserves the event subscription state for the toolbar.

🔒 Security Vulnerabilities

  • No security vulnerabilities detected. The changes are restricted to internal UI eventing and state synchronization. 🛡️

Objective

  • Synchronize the toolbar's selection controls with the editor's selection menu visibility state.

Solution

  • Introduced a new EditorEvent and a subscription mechanism in the toolbar controls to react to state changes.

Testing

  • Verified via new automated test suite in selection_controls.rs.

Self-Review Checklist:

  • I've reviewed my own diff for quality, security, and reliability
  • Unsafe blocks (if any) have justifying comments
  • The content adheres to Zed's UI standards
  • Tests cover the new/changed behavior
  • Performance impact has been considered and is acceptable

Showcase

  • N/A

Release Notes:

  • Improved toolbar responsiveness when toggling selection menus in the editor.

@coderabbitai

coderabbitai Bot commented Jun 20, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 342255de-c93e-4dcc-b6a5-05c2f5b99312

📥 Commits

Reviewing files that changed from the base of the PR and between ce7366d and c1ebeef.

📒 Files selected for processing (2)
  • crates/editor/src/editor.rs
  • crates/editor/src/selection_controls.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • crates/editor/src/selection_controls.rs

📝 Walkthrough

Walkthrough

Three new policy structs control which context-menu action groups (language, agent, preview, terminal, git, workspace-folder, search, compare) appear in Editor, ProjectPanel, and Pane context menus. Each policy is stored on its component, initialized to full, and enforced throughout menu builders. A new EditorSelectionControls toolbar component centralizes selection-menu UI. File finder toggle logic is extracted into a helper function. ProjectPanel gains a reveal_abs_path method and Workspace exposes a modal_layer accessor. Quick action bar is refactored to use the new selection controls component.

Changes

Policies, Selection Controls, and UI Integration

Layer / File(s) Summary
Policy type definitions and component integration
crates/editor/src/editor.rs, crates/project_panel/src/project_panel.rs, crates/workspace/src/pane.rs
Defines EditorSurfacePolicy, ProjectPanelContextMenuPolicy, and PaneContextMenuPolicy with boolean action-group flags and full()/embedded() constructors; adds policy field to each component, initializes in constructors, and exposes set_*_policy setters that call cx.notify() only on change. EditorEvent::SelectionMenuChanged variant added for selection-menu toggle events.
Editor context menu action gating
crates/editor/src/mouse_context_menu.rs, crates/editor/src/items.rs, crates/editor/src/editor.rs
deploy_context_menu gates git availability, markdown/SVG preview detection, language-actions group, agent-action, and terminal/git sections behind corresponding surface_policy flags. tab_extra_context_menu_actions early-returns empty when show_preview_actions is false. toggle_selection_menu now emits SelectionMenuChanged only when enabled state actually changes.
Project panel and pane context menu action gating
crates/project_panel/src/project_panel.rs, crates/workspace/src/pane.rs
Project panel gates compare, git, search, terminal, and workspace-folder actions using context_menu_policy booleans in deploy_context_menu. Pane makes parent_abs_path conditional on show_terminal_actions, returning None when disabled to suppress terminal menu entries.
ProjectPanel::reveal_abs_path helper
crates/project_panel/src/project_panel.rs
Adds public method that resolves absolute filesystem path to ProjectPath/entry_id, synchronously seeds expanded_dir_ids for worktree root when missing, and calls reveal_entry with skip_ignored=true; errors when path not part of project or unloaded.
Selection controls UI component
crates/editor/src/selection_controls.rs
Creates new module exporting SelectionControlsMenuOptions for configurable menu items, menu builders for select-all/navigate-occurrences/expand-syntax/add-cursors actions, popover helpers, and EditorSelectionControls—a toolbar component that tracks active editor, observes SettingsStore and EditorEvent::SelectionMenuChanged, emits ToolbarItemEvent based on selection_menu_enabled flag, and renders selection-controls popover or disabled/empty placeholders.
File finder toggle helper extraction
crates/file_finder/src/file_finder.rs
Extracts ToggleFileFinder action's inline modal logic into new public toggle_file_finder helper that either opens FileFinder modal when absent or updates init_modifiers and cycles picker when active.
Workspace modal layer accessor
crates/workspace/src/workspace.rs
Adds public Workspace::modal_layer() getter that returns workspace's modal_layer entity for embedders rendering Workspace outside of MultiWorkspace.
Quick action bar selection menu refactor
crates/zed/src/zed/quick_action_bar.rs
Refactors selection dropdown to delegate core items to selection_controls_menu_items with SelectionControlsMenuOptions::without_duplicate_selection() and uses selection_controls_popover_with_menu; preserves "Add to Agent Thread" disabling logic and trailing navigation/actions; adjusts imports.
Policy enforcement and feature tests
crates/editor/src/editor_tests.rs, crates/project_panel/src/project_panel_tests.rs, crates/workspace/src/pane.rs
Editor test setup sets surface_policy to embedded() and verifies cloned editors retain it; new editor test asserts embedded() hides language/agent/preview/terminal/git actions and default() equals full(); project panel unit test verifies embedded() disables all action groups; project panel UI test validates reveal_abs_path seeds missing expanded state; pane test asserts embedded() hides terminal actions.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~28 minutes

Poem

🐇 Three policies hop in place,
Each menu item knows its space.
Selection controls wear toolbar crown,
While file finder toggles up and down.
Full or embedded—take your pick,
The rabbit's refactor: clean and slick! 🥕

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 70.97% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main objective of adding embedded surface policies for Cherrypick's file editor integration.
Description check ✅ Passed The PR description comprehensively covers the objective, solution, testing approach, and self-review checklist with all required sections properly filled out.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/code-editor

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Add policy-driven context menus for embedded editor and project panel
✨ Enhancement 🐞 Bug fix 🕐 20-40 Minutes

Grey Divider

Description

• Add policy structs to selectively hide editor/pane/project-panel context menu actions.
• Gate preview, language, agent, terminal, and git actions for embed-friendly surfaces.
• Fix project panel reveals that could fail before the tree’s expanded state is seeded.
Diagram

graph TD
  A["Host Surface"] --> B["Workspace Pane"] --> C["Editor"] --> D["Editor Context Menu"]
  C --> E("EditorSurfacePolicy")
  A --> F["Project Panel"] --> G["Project Context Menu"]
  F --> H("ProjectPanelPolicy")
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Use bitflags for policies
  • ➕ Scales better as more actions/sections are added
  • ➕ Easier to compose policies (OR/AND) and serialize if needed
  • ➖ Less self-documenting than named booleans for small policy sets
  • ➖ Slightly more cognitive overhead for contributors unfamiliar with bitflags
2. Centralize policies as an embedding/feature-capability service
  • ➕ Single source of truth for embed modes across editor/pane/project panel
  • ➕ Enables dynamic policies based on workspace/project capabilities
  • ➖ More plumbing and indirection for what is currently simple gating
  • ➖ Harder to reason about locally in each component

Recommendation: The current per-component policy structs are a pragmatic, low-risk way to curate UI in embedded contexts, and they keep gating logic close to where actions are defined. If these policies grow significantly or need composition/serialization, consider migrating to bitflags to avoid boolean explosion while preserving clear presets (e.g., full vs embedded).

Files changed (5) +290 / -74

Enhancement (4) +170 / -60
editor.rsIntroduce EditorSurfacePolicy and store it on Editor +47/-0

Introduce EditorSurfacePolicy and store it on Editor

• Adds an EditorSurfacePolicy with presets (full, file_editor) and default initialization. Stores the policy on Editor and exposes set_surface_policy to update it and trigger a UI refresh.

crates/editor/src/editor.rs

items.rsHide preview-related actions based on editor surface policy +4/-1

Hide preview-related actions based on editor surface policy

• Short-circuits the preview actions list when the surface policy disables preview actions. Prevents embedded/editor-lite surfaces from advertising preview actions via the Item action list.

crates/editor/src/items.rs

mouse_context_menu.rsGate editor context menu sections via EditorSurfacePolicy +72/-56

Gate editor context menu sections via EditorSurfacePolicy

• Threads EditorSurfacePolicy into context menu construction to conditionally include language/navigation/code-action items, agent actions, preview detection/actions, terminal actions, and git actions. Also avoids computing git/preview state when those sections are disabled.

crates/editor/src/mouse_context_menu.rs

pane.rsAdd pane context-menu policy to disable terminal-derived paths +47/-3

Add pane context-menu policy to disable terminal-derived paths

• Introduces PaneContextMenuPolicy and a setter to update it with UI notification. Uses the policy to avoid computing parent paths for terminal actions when terminal actions are disabled in the pane context menu.

crates/workspace/src/pane.rs

Bug fix (1) +120 / -14
project_panel.rsAdd project panel context-menu policy + robust reveal_abs_path +120/-14

Add project panel context-menu policy + robust reveal_abs_path

• Introduces ProjectPanelContextMenuPolicy with presets and uses it to conditionally show terminal/search/compare/git/workspace-folder actions in the project panel context menu. Adds reveal_abs_path, including a fix that seeds expanded root state to ensure reveals expand correctly when invoked before async visible-entry seeding completes.

crates/project_panel/src/project_panel.rs

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces context menu policies (EditorSurfacePolicy, ProjectPanelContextMenuPolicy, and PaneContextMenuPolicy) to conditionally show or hide actions in the editor, project panel, and pane context menus. It also adds a helper method reveal_abs_path to ProjectPanel to reveal a project entry at an absolute path. The feedback suggests simplifying a nested if/else block in pane.rs and renaming abbreviated variables like abs_path and ext to full words (absolute_path, path, and extension) to adhere to the repository style guide.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread crates/workspace/src/pane.rs Outdated
Comment on lines +3316 to +3323
let parent_abs_path =
if pane.read(cx).context_menu_policy.show_terminal_actions {
entry_abs_path
.as_deref()
.and_then(|abs_path| Some(abs_path.parent()?.to_path_buf()))
} else {
None
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The nested if/else block can be simplified using bool::then and .flatten(). Additionally, the closure parameter abs_path should be renamed to path to avoid abbreviations, adhering to the repository style guide.

                            let parent_abs_path = pane
                                .read(cx)
                                .context_menu_policy
                                .show_terminal_actions
                                .then(|| {
                                    entry_abs_path
                                        .as_deref()
                                        .and_then(|path| path.parent().map(|p| p.to_path_buf()))
                                })
                                .flatten();
References
  1. Use full words for variable names (no abbreviations like 'q' for 'queue'). (link)

Comment on lines +6437 to +6449
pub fn reveal_abs_path(
&mut self,
project: Entity<Project>,
abs_path: &Path,
window: &mut Window,
cx: &mut Context<Self>,
) -> Result<()> {
let Some(project_path) = project
.read(cx)
.project_path_for_absolute_path(abs_path, cx)
else {
anyhow::bail!("path is not part of the project");
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The parameter abs_path should be renamed to absolute_path to avoid abbreviations, adhering to the repository style guide.

    pub fn reveal_abs_path(
        &mut self,
        project: Entity<Project>,
        absolute_path: &Path,
        window: &mut Window,
        cx: &mut Context<Self>,
    ) -> Result<()> {
        let Some(project_path) = project
            .read(cx)
            .project_path_for_absolute_path(absolute_path, cx)
        else {
            anyhow::bail!("path is not part of the project");
        };
References
  1. Use full words for variable names (no abbreviations like 'q' for 'queue'). (link)

Comment thread crates/editor/src/mouse_context_menu.rs Outdated
.is_some_and(|file| {
std::path::Path::new(file.file_name(cx))
.extension()
.is_some_and(|ext| ext.eq_ignore_ascii_case("svg"))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The closure parameter ext should be renamed to extension to avoid abbreviations, adhering to the repository style guide.

Suggested change
.is_some_and(|ext| ext.eq_ignore_ascii_case("svg"))
.is_some_and(|extension| extension.eq_ignore_ascii_case("svg"))
References
  1. Use full words for variable names (no abbreviations like 'q' for 'queue'). (link)

@matterai-app

matterai-app Bot commented Jun 20, 2026

Copy link
Copy Markdown

✅ Reviewed the changes: Clean, well-structured PR introducing surface-specific context menu policies across Editor, ProjectPanel, and Pane. Reviewed crates/editor/src/editor.rs: no issues found. Reviewed crates/editor/src/mouse_context_menu.rs: no issues found. Reviewed crates/project_panel/src/project_panel.rs: no issues found. Reviewed crates/workspace/src/pane.rs: no issues found.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds configurable “policy” flags to control which context-menu actions are available across editor surfaces, panes, and the project panel, plus a new helper to reliably reveal a path in the project panel even during early-mount timing.

Changes:

  • Introduced policy structs + setters to enable/disable groups of context-menu actions in the editor, pane tab menu, and project panel.
  • Updated editor and project panel context menus to conditionally include terminal/git/preview/language/agent/compare/search/workspace actions based on policy.
  • Added ProjectPanel::reveal_abs_path with state seeding to avoid a race where reveal/expand could silently no-op shortly after mount.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
crates/workspace/src/pane.rs Add PaneContextMenuPolicy + setter and gate “Open in Terminal” tab action accordingly.
crates/project_panel/src/project_panel.rs Add ProjectPanelContextMenuPolicy + setter, gate context-menu sections, and add reveal_abs_path to fix early reveal expansion race.
crates/editor/src/mouse_context_menu.rs Respect EditorSurfacePolicy flags when building the editor mouse context menu.
crates/editor/src/items.rs Hide preview-related item actions when preview actions are disabled by policy.
crates/editor/src/editor.rs Add EditorSurfacePolicy + setter to configure which action groups are available on an editor surface.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread crates/editor/src/editor.rs Outdated
Comment on lines +617 to +625
pub const fn file_editor() -> Self {
Self {
show_language_actions: false,
show_agent_actions: false,
show_preview_actions: false,
show_terminal_actions: false,
show_git_actions: false,
}
}
Comment thread crates/workspace/src/pane.rs Outdated
Comment on lines +409 to +413
pub const fn file_editor() -> Self {
Self {
show_terminal_actions: false,
}
}
Comment on lines +6457 to +6476
// `reveal_entry` -> `expand_entry` only records expanded ancestors when the
// worktree already has an `expanded_dir_ids` entry. That map is seeded
// asynchronously by `update_visible_entries` (its vacant branch inserts the
// root entry), so a reveal issued right after mount can beat it
// and `expand_entry`'s `get_mut` returns `None` — it silently no-ops and the
// tree never expands to the target file. Seed the worktree root here if
// it's still vacant (same value `update_visible_entries` would insert) so
// `expand_entry` writes the ancestors into `self.state` synchronously; every
// later `update_visible_entries` derives from that state and preserves them.
let worktree_id = project_path.worktree_id;
if !self.state.expanded_dir_ids.contains_key(&worktree_id)
&& let Some(root_id) = project
.read(cx)
.worktree_for_id(worktree_id, cx)
.and_then(|worktree| worktree.read(cx).root_entry().map(|entry| entry.id))
{
self.state
.expanded_dir_ids
.insert(worktree_id, vec![root_id]);
}
@qodo-code-review

qodo-code-review Bot commented Jun 20, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Remediation recommended

1. Mixed project source ✓ Resolved 🐞 Bug ≡ Correctness
Description
ProjectPanel::reveal_abs_path takes a caller-supplied Project and uses it to resolve worktree/entry
ids, but the reveal path later calls expand_entry which mutates/reads via self.project. If a caller
ever passes a different Project entity than the panel’s own, the reveal can act on inconsistent
project state (e.g. expanding/updating visibility in the panel’s project using ids derived from a
different project).
Code

crates/project_panel/src/project_panel.rs[R6437-6478]

+    pub fn reveal_abs_path(
+        &mut self,
+        project: Entity<Project>,
+        abs_path: &Path,
+        window: &mut Window,
+        cx: &mut Context<Self>,
+    ) -> Result<()> {
+        let Some(project_path) = project
+            .read(cx)
+            .project_path_for_absolute_path(abs_path, cx)
+        else {
+            anyhow::bail!("path is not part of the project");
+        };
+        let Some(entry_id) = project
+            .read(cx)
+            .entry_for_path(&project_path, cx)
+            .map(|entry| entry.id)
+        else {
+            anyhow::bail!("path has not been loaded in the project panel");
+        };
+        // `reveal_entry` -> `expand_entry` only records expanded ancestors when the
+        // worktree already has an `expanded_dir_ids` entry. That map is seeded
+        // asynchronously by `update_visible_entries` (its vacant branch inserts the
+        // root entry), so a reveal issued right after mount can beat it
+        // and `expand_entry`'s `get_mut` returns `None` — it silently no-ops and the
+        // tree never expands to the target file. Seed the worktree root here if
+        // it's still vacant (same value `update_visible_entries` would insert) so
+        // `expand_entry` writes the ancestors into `self.state` synchronously; every
+        // later `update_visible_entries` derives from that state and preserves them.
+        let worktree_id = project_path.worktree_id;
+        if !self.state.expanded_dir_ids.contains_key(&worktree_id)
+            && let Some(root_id) = project
+                .read(cx)
+                .worktree_for_id(worktree_id, cx)
+                .and_then(|worktree| worktree.read(cx).root_entry().map(|entry| entry.id))
+        {
+            self.state
+                .expanded_dir_ids
+                .insert(worktree_id, vec![root_id]);
+        }
+        self.reveal_entry(project, entry_id, true, window, cx)
+    }
Evidence
The new API resolves entry ids from the passed-in project, but the subsequent expansion step uses
self.project.update(...), so the code path mixes two different project sources and implicitly
assumes they are identical.

crates/project_panel/src/project_panel.rs[6437-6478]
crates/project_panel/src/project_panel.rs[6480-6534]
crates/project_panel/src/project_panel.rs[4426-4457]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`ProjectPanel::reveal_abs_path` accepts an external `project: Entity<Project>` and uses it for path->entry resolution, but the reveal flow ultimately calls `expand_entry`, which operates via `self.project`. This creates an implicit requirement that callers *must* pass the panel’s own project entity; otherwise the reveal can become inconsistent.
### Issue Context
- `reveal_abs_path` resolves `project_path` and `entry_id` from the passed-in `project`, then calls `self.reveal_entry(project, entry_id, ...)`.
- `reveal_entry` calls `self.expand_entry(worktree_id, entry_id, cx)`.
- `expand_entry` performs its updates through `self.project.update(...)` and relies on `self.state.expanded_dir_ids` for `worktree_id`.
### How to fix
Prefer eliminating the possibility of mismatch:
1. Change `reveal_abs_path` to *not* accept a `project` parameter; instead use `self.project.clone()` internally for `project_path_for_absolute_path`, `entry_for_path`, and subsequent calls.
2. Similarly consider removing the `project: Entity<Project>` parameter from `reveal_entry` (and updating its internal call sites) so the panel always uses its own canonical project.
3. If you must keep the parameter for ergonomic reasons, add a defensive assertion/check that the passed `project` matches `self.project` (e.g., compare entity ids) and bail early with a clear error if not.
### Fix Focus Areas
- crates/project_panel/src/project_panel.rs[6437-6534]
- crates/project_panel/src/project_panel.rs[4426-4457]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/editor/src/editor.rs`:
- Line 1120: The `surface_policy` field added to the `Editor` struct is not
being copied when the editor is cloned. To fix this, locate the `Clone`
implementation or clone method for the `Editor` struct and ensure that the
`surface_policy` field is explicitly copied along with all other fields when
creating the cloned instance. This will prevent clones from silently falling
back to the default surface policy value.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ea7afb31-c458-4730-8fa2-fcee55df620a

📥 Commits

Reviewing files that changed from the base of the PR and between 45e8438 and 50b53ac.

📒 Files selected for processing (5)
  • crates/editor/src/editor.rs
  • crates/editor/src/items.rs
  • crates/editor/src/mouse_context_menu.rs
  • crates/project_panel/src/project_panel.rs
  • crates/workspace/src/pane.rs

Comment thread crates/editor/src/editor.rs

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

5 issues found across 5 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="crates/project_panel/src/project_panel.rs">

<violation number="1" location="crates/project_panel/src/project_panel.rs:3958">
P3: New context-menu policy wiring is unused; added policy branches are unreachable from current code paths.</violation>
</file>

<file name="crates/editor/src/editor.rs">

<violation number="1" location="crates/editor/src/editor.rs:3006">
P2: `set_surface_policy` is unused, so `surface_policy` stays default and non-default surface behavior is currently unreachable.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread crates/editor/src/editor.rs
Comment thread crates/workspace/src/pane.rs
self.in_project_search = in_project_search;
}

pub fn set_surface_policy(&mut self, policy: EditorSurfacePolicy, cx: &mut Context<Self>) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: set_surface_policy is unused, so surface_policy stays default and non-default surface behavior is currently unreachable.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At crates/editor/src/editor.rs, line 3006:

<comment>`set_surface_policy` is unused, so `surface_policy` stays default and non-default surface behavior is currently unreachable.</comment>

<file context>
@@ -2964,6 +3003,14 @@ impl Editor {
         self.in_project_search = in_project_search;
     }
 
+    pub fn set_surface_policy(&mut self, policy: EditorSurfacePolicy, cx: &mut Context<Self>) {
+        if self.surface_policy == policy {
+            return;
</file context>

Comment thread crates/editor/src/editor.rs Outdated
})
}

pub fn set_context_menu_policy(

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: New context-menu policy wiring is unused; added policy branches are unreachable from current code paths.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At crates/project_panel/src/project_panel.rs, line 3958:

<comment>New context-menu policy wiring is unused; added policy branches are unreachable from current code paths.</comment>

<file context>
@@ -3905,6 +3955,18 @@ impl ProjectPanel {
         })
     }
 
+    pub fn set_context_menu_policy(
+        &mut self,
+        policy: ProjectPanelContextMenuPolicy,
</file context>

@soyboyscout soyboyscout changed the title Feat/code editor Add embedded surface policies for Cherrypick file editor Jun 21, 2026

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 5 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="crates/project_panel/src/project_panel.rs">

<violation number="1" location="crates/project_panel/src/project_panel.rs:3958">
P3: New context-menu policy wiring is unused; added policy branches are unreachable from current code paths.</violation>
</file>

<file name="crates/editor/src/editor.rs">

<violation number="1" location="crates/editor/src/editor.rs:3006">
P2: `set_surface_policy` is unused, so `surface_policy` stays default and non-default surface behavior is currently unreachable.</violation>
</file>

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread crates/editor/src/selection_controls.rs

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/editor/src/selection_controls.rs`:
- Around line 125-130: The settings_subscription at line 125 only observes
SettingsStore changes but does not track changes to the editor-local
show_selection_menu state that affects selection_menu_enabled. Add a separate
subscription (in addition to the existing SettingsStore observation) that
observes the active editor state to detect when show_selection_menu changes, and
emit the ToolbarItemEvent::ChangeLocation event with the updated
toolbar_item_location in response to these editor state changes to keep toolbar
visibility in sync.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9fa56813-aa15-44b8-b04e-9a50cd13e0cd

📥 Commits

Reviewing files that changed from the base of the PR and between 50b53ac and ce7366d.

📒 Files selected for processing (10)
  • crates/editor/src/editor.rs
  • crates/editor/src/editor_tests.rs
  • crates/editor/src/mouse_context_menu.rs
  • crates/editor/src/selection_controls.rs
  • crates/file_finder/src/file_finder.rs
  • crates/project_panel/src/project_panel.rs
  • crates/project_panel/src/project_panel_tests.rs
  • crates/workspace/src/pane.rs
  • crates/workspace/src/workspace.rs
  • crates/zed/src/zed/quick_action_bar.rs
🚧 Files skipped from review as they are similar to previous changes (2)
  • crates/editor/src/mouse_context_menu.rs
  • crates/workspace/src/pane.rs

Comment thread crates/editor/src/selection_controls.rs
@soyboyscout soyboyscout merged commit 026219c into main Jun 21, 2026
38 of 40 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants